import block
from block import Block, Restriction, Slot, Section
import agent
from agent import Agent
import world
from world import BlockStack, World
import const
import channel
from channel import Channel
import threading
from threading import Thread
import string
import random
import time

f = open("colors","r")
colors=f.readlines()
colors = map (string.rstrip, colors)
f.close()

block_id = -1
blocks = []

def genBlock():
	global block_id
	block_id = block_id + 1
	b =  block.createBlock(block_id, random.choice(colors),
		random.randint(0, 10), 
		random.randint(0, 10), 
		random.randint(0, 10))
	blocks.append(b)
	return b

def genStack():
	dist = random.randint(0, 10)
	num = random.randint(7, 10)
	blocks = []
	for i in range(num):
		blocks.append(genBlock())
	return BlockStack(dist, blocks)

def genWorld():
	num = random.randint(7, 12)
	stacks = []
	for i in range(num):
		stacks.append(genStack())
	return World(stacks)

def genSign():
	x = random.randint(0, 3)
	if x == 0: return const.LT
	if x == 1: return const.GT
	if x == 2: return const.LE
	if x == 3: return const.GE

def genRestriction():
	type = random.randint(0, 3)
	if type == 0:
		return Restriction(const.COLOR, random.choice(colors), const.EQ)
	if type == 1:
		return Restriction(const.WEIGHT, random.randint(2, 8), genSign())
	if type == 2:
		return Restriction(const.HEIGHT, random.randint(2, 8), genSign())
	if type == 3:
		return Restriction(const.WIDTH, random.randint(2, 8), genSign())

def genSlot():
	num = random.randint(0, 3)
	restr = []
	for i in range(num):
		restr.append(genRestriction())
	return Slot(restr)

numAgent = -1
world = genWorld()

def genAgent():
	global numAgent
	numAgent+=1
	numsections = random.randint(1, 3)
	sections = []
	for i in range(numsections):
		numslots = random.randint(2,5)
		slots = []
		for j in range(numslots):
			slot = genSlot()
			while not filter(slot.fits, blocks):
				slot = genSlot()
			slots.append(slot)
		sections.append(Section(slots))
	return Agent("agent" + str(numAgent),  world, sections)

agents = []
for i in range(10):
	agents.append(genAgent())

channel = Channel(agents)

for agent in agents:
	agent.setChannel(channel)

class RunAgent(Thread):
	def __init__(self, agent):
		Thread.__init__(self)
		self.agent = agent

	def run(self):
		self.agent.runAgent()

runagents = []
for agent in agents:
	runagents.append(RunAgent(agent))
	runagents[-1].start()

for r in runagents:
	r.join()

time.sleep(0.1)

#matched = 0
#initial = 0
#shared = 0
#for agent in agents:
#	for block in agent.usedBlocks:
#		slot = agent.usedBlocks[block]
#	agent_matched = agent.countMatchedSlots()
#	agent_initial = agent.countInitialSlots()
#	agent_shared = agent.countSharedSlots()
#	agent_total = agent.countTotalSlots()
#
#	agent_matched -= agent_total - agent_initial
#	agent_shared -= agent_total - agent_initial
#
#	# initial = slots in agent's initial goals
#	# matched = slots out of the initial slots that have blocks in them
#	# shared = slots out of the initial ones that are shared
#
#	matched += agent_matched
#	initial += agent_initial
#	shared += agent_shared
#
#	for b in agent.usedBlocks:
#		isIn = False
#		for goal in agent.goalstacks:
#			if agent.usedBlocks[b] in goal.slots:
#				isIn = True
#		if not isIn:
#			print "->>>>>>>>>> Foreign slot ", str(agent.usedBlocks[b]), " for agent " , agent.name, " filled by block ", b
#
#	for b1 in agent.usedBlocks:
#		for b2 in agent.usedBlocks:
#			if b1 != b2 and agent.usedBlocks[b1] == agent.usedBlocks[b2]:
#				print "->>>>>>>>>> Two blocks for same slot", b1, "and", b2, "for slot", agent.usedBlocks[b1], "for agent", agent.name
#		
#
#	print "Agent", agent.name, ":", agent_matched, "matched, ", \
#									agent_shared, "shared, ", 	\
#									agent_initial, "initial, ",	\
#									agent_total, "total"
#
#print len(blocks), "blocks"
#print "matched slots: ", matched, "/", initial, "(of which", shared, "shared)"
#
#

#for agent in agents:
	#print agent.name, ":\n\t",
	#a=0
	#for stack in world.stacks:
	#	for b in stack.blocks:
	#		if b.owner == agent.name:
	#			a += 1
	#			print b.id,
	#print "\t", a, "blocks"
	#print map (str,agent.makeGoals())
	#print

#print "\n\nWorld\n"
#print map(str, world.worldState())
